﻿using System.ComponentModel;
using XYS.Core.Util;

namespace XYS.Core.Models
{
    /// <summary>
    /// 泛型基础返回模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ResultModel<T> : ResultModel
    {
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <typeparam name="T2"></typeparam>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed<T2>(ResultModel<T2> result) => new() { Succeeded = false, Error = result.Error, StatusCode = result.StatusCode };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed(ResultModel result) => new() { Succeeded = false, Error = result.Error, StatusCode = result.StatusCode };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed(int statusCode, string error, T result) => new() { Succeeded = false, Error = error, StatusCode = statusCode, Data = result };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static new ResultModel<T> Failed(int statusCode, string error) => new() { Succeeded = false, Error = error, StatusCode = statusCode };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static new ResultModel<T> Failed(string error, int statusCode) => new() { Succeeded = false, Error = error, StatusCode = statusCode };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed(string error, int statusCode, T result) => new() { Succeeded = false, Error = error, StatusCode = statusCode, Data = result };



        /// <summary>
        /// 返回成功模型
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static new ResultModel<T> Success(T result) => new() { Data = result, Succeeded = true, StatusCode = (int)EnumStatusCode.OK };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed(EnumStatusCode statusCode, string error, T result) => new() { Succeeded = false, Error = error, StatusCode = (int)statusCode, Data = result };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static new ResultModel<T> Failed(EnumStatusCode statusCode, string error) => new() { Succeeded = false, Error = error, StatusCode = (int)statusCode };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static new ResultModel<T> Failed(string error, EnumStatusCode statusCode = EnumStatusCode.InternalServerError) => new() { Succeeded = false, Error = error, StatusCode = (int)statusCode };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed(string error, EnumStatusCode statusCode, T result) => new() { Succeeded = false, Error = error, StatusCode = (int)statusCode, Data = result };


        /// <summary>
        /// 结果集
        /// </summary>
        public T Data { get; set; }
    }

    /// <summary>
    /// 基础返回模型
    /// </summary>
    public class ResultModel
    {
        private static readonly ResultModel _success = new()
        {
            Succeeded = true,
            StatusCode = (int)EnumStatusCode.OK
        };

        /// <summary>
        /// 返回成功模型
        /// </summary>
        /// <returns></returns>
        public static ResultModel Success => _success;
        /// <summary>
        /// 返回成功模型
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Successed<T>(T result) => new() { Data = result, Succeeded = true, StatusCode = (int)EnumStatusCode.OK };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed<T>(ResultModel<T> result) => new() { Succeeded = false, Error = result.Error, StatusCode = result.StatusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="error"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed<T>(string error, int statusCode = 500) => new() { Succeeded = false, Error = error, StatusCode = statusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="error"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed<T>(string error, EnumStatusCode statusCode) => Failed<T>(error, (int)statusCode);

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="result"></param>
        /// <returns></returns>
        public static ResultModel Failed<T>(ResultModel result) => new() { Succeeded = false, Error = result.Error, StatusCode = result.StatusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static ResultModel<T> Failed<T>(Exception e) => new() { Succeeded = false, Error = e.ToJson(), StatusCode = 500 };

        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static ResultModel Failed(EnumStatusCode statusCode, string error) => new() { Succeeded = false, Error = error, StatusCode = (int)statusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static ResultModel Failed(Exception e) => new() { Succeeded = false, Error = e.ToJson(), StatusCode = 500 };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static ResultModel Failed(int statusCode, string error) => new() { Succeeded = false, Error = error, StatusCode = statusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static ResultModel Failed(string error, EnumStatusCode statusCode) => new() { Succeeded = false, Error = error, StatusCode = (int)statusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static ResultModel Failed(string error, int statusCode) => new() { Succeeded = false, Error = error, StatusCode = statusCode };
        /// <summary>
        /// 返回失败模型
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public static ResultModel Failed(string error) => new() { Succeeded = false, Error = error, StatusCode = (int)EnumStatusCode.InternalServerError };

        /// <summary>
        /// 是否成功
        /// </summary>
        [DefaultValue(true)]
        public bool Succeeded { get; set; }
        /// <summary>
        /// 状态码
        /// 默认可使用 HttpStatusCode 枚举的状态码，如果该枚举无法满足业务时，可扩展（为防止和 HttpStatusCode 枚举冲突，建议自定义的错误码从 1000 开始）
        /// 5开头的状态码，表示前端仅仅在浏览器控制台打印出来，方便定位问题，但向用户展示时，可以使用全局统一的话术，例如：系统正在开小差，请稍后重试！
        /// </summary>
        public int StatusCode { get; set; } = (int)EnumStatusCode.OK;
        /// <summary>
        /// 异常消息
        /// </summary>
        [DefaultValue(null)]
        public string Error { get; set; }
    }

}
